home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Revolution - Das Atari CD Magazin 1997
/
Revolution - Das Atari CD Magazin 1.iso
/
software
/
anwendng
/
qed_397
/
sourcen
/
windows.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-01-17
|
43KB
|
1,622 lines
#include "global.h"
#include "av.h"
#include "comm.h"
#include "desktop.h"
#include "event.h"
#include "fontsel.h"
#include "icon.h"
#include "magx.h"
#include "makro.h"
#include "menu.h"
#include "obj.h"
#include "options.h"
#include "rsc.h"
#include "scroll.h"
#include "set.h"
#include "windows.h"
VOID clr_undo (VOID); /* aus CLIPBRD.H */
/*
* exportierte Variablen
*/
GLOBAL WINDP sel_window; /* Zeiger auf selektiertes Fenster */
GLOBAL SET sel_objs; /* Menge selektierter Objekte */
GLOBAL BOOLEAN all_iconified;
/****** DEFINES ************************************************************/
#ifndef WM_BOTTOMED
#define WM_BOTTOMED 33
#endif
#ifndef WF_ICONIFY
#define WF_ICONIFY 26
#define WF_UNICONIFY 27
#define WF_UNICONIFYXYWH 28
#endif
#define MIN_WIDTH (8 * sys_wchar) /* Kleinste Breite */
#define MIN_HEIGHT (8 * sys_hchar) /* Kleinste Höhe */
#define WORK_MOVED 0x01 /* Für Verschieben und Vergrößern */
#define WORK_SIZED 0x02
#define MAX_WINDOW 19
/****** TYPES **************************************************************/
/****** VARIABLES **********************************************************/
LOCAL WINDOW windrec[MAX_WINDOW]; /* Speicher für Fenster */
LOCAL RECT border; /* für rc_first/next */
LOCAL WINDP free_list; /* ROOT der unbenutzten Fenster */
LOCAL WINDP used_list; /* ROOT der benutzten Fenster */
LOCAL WORD age, top_handle;
LOCAL WINDP icon_win;
LOCAL WORD opened_win[MAX_WINDOW]; /* Iconnummer der offen gewesenen Fenster
* [0] enthält die Anzahl !!
*/
/****** FUNCTIONS **********************************************************/
LOCAL VOID move_to_top (WINDP window);
LOCAL VOID move_to_end (WINDP window);
LOCAL VOID get_work (WINDP window, RECT *new, WORD mode);
LOCAL VOID do_arrow (WINDP window, WORD dir, long delta);
LOCAL VOID default_snap (WINDP window, RECT *new, WORD mode);
/***************************************************************************/
VOID add_windinfo(WORD class, RECT *r, WORD icon_x, WORD icon_y, WORD init)
{
WORD i;
WINDP window;
switch (class)
{
case 2 : class = CLASS_EDIT; break;
case 3 : class = CLASS_CLIP; break;
case 4 : class = CLASS_PROJEKT; break;
case 5 : class = CLASS_TRASH; break;
default: return;
}
for (i=MAX_WINDOW,window=windrec; (--i)>=0; window++)
{
if (r==NULL) /* Nur Iconpos setzen */
{
if (window->icon_x==0 && window->icon_y==0 &&
window->class==class) /* Ohne Iconpos */
{
window->icon_x = icon_x;
window->icon_y = icon_y;
break;
}
}
else
{
if (window->work.w == 0) /* Ohne Info */
{
window->class = class;
window->work = *r;
window->icon_x = icon_x;
window->icon_y = icon_y;
window->init = init;
break;
}
}
}
}
BOOLEAN get_windinfo(WORD *last, WORD *class, RECT *r, WORD *icon_x,
WORD *icon_y, WORD *used)
{
WORD i, nr;
WINDP window;
i = *last+1;
if (i >= age)
return FALSE;
retry:
*used = 0;
nr = 1;
for (window = free_list; window != NULL && window->age != i; window = window->next)
;
if (window == NULL)
{
for (window = used_list; window != NULL && window->age != i; window=window->next, nr++)
;
if (window!=NULL)
{
*used = nr;
}
}
if (window==NULL || window->class==DESK || window->work.w==0)
{
i++;
if (i == age)
return FALSE;
goto retry;
}
*r = window->work;
*icon_x = window->icon_x;
*icon_y = window->icon_y;
switch (window->class)
{
case CLASS_EDIT : *class = 2; break;
case CLASS_CLIP : *class = 3; break;
case CLASS_PROJEKT:*class = 4; break;
case CLASS_TRASH: *class = 5; break;
}
*last = i;
return TRUE;
}
BOOLEAN rc_first(WORD wh, CONST RECT *b, RECT *r)
{
border = *b;
if (!myrc_intersect(&desk,&border)) /* mit Bildschirm schneiden */
return FALSE;
wind_get (wh, WF_FIRSTXYWH, &r->x, &r->y, &r->w, &r->h);
while (r->w && r->h)
{
if (myrc_intersect (&border, r)) /* Schneide Rechtecke */
return TRUE;
wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
}
return FALSE;
}
BOOLEAN rc_next(WORD wh, RECT *r)
{
wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
while (r->w && r->h)
{
if (myrc_intersect (&border, r)) /* Schneide Rechtecke */
return TRUE;
wind_get (wh, WF_NEXTXYWH, &r->x, &r->y, &r->w, &r->h);
}
return FALSE;
}
/************************************************************************/
/* Suche nach Fenster */
/************************************************************************/
WINDP get_window (WORD link)
{
WINDP w;
for (w=used_list; w!=NULL ; w=w->next)
{
if (link==w->link) return (w);
}
return (NULL);
} /* get_window */
/***************************************************************************/
/* Suche Fenster von Fenster-Handle */
/***************************************************************************/
WINDP find_window (WORD wh)
{
WINDP w;
/*
* Fenster 0 nur dann sinnvoll, wenn qed-Desktop aktiv.
* Sonst wird NULL geliefert, damit D&D zu Thing möglich wird!
*/
if ((wh != 0) || ((wh == 0) && (!no_desktop)))
{
for (w=used_list; w!=NULL; w=w->next)
{
if (wh==w->handle) return (w);
}
}
return (NULL);
} /* find_window */
/***************************************************************************/
/* Suche oberstes Fenster */
/***************************************************************************/
WINDP top (VOID)
{
WINDP w;
for (w=used_list; w!=NULL && w->opened; w=w->next)
return w;
return NULL;
}
VOID get_realtop(VOID)
{
wind_get (0, WF_TOP, &top_handle);
}
WINDP real_top (VOID)
{
WINDP window;
window = top();
if (window==NULL) return NULL;
return ((window->handle==top_handle) ? window : NULL);
}
BOOLEAN free_for_draw(WINDP window)
{
RECT draw;
if (rc_first(window->handle, &window->work, &draw))
{
if (window->work.w == draw.w && window->work.h == draw.h)
return TRUE;
}
return FALSE;
}
/***************************************************************************/
/* Zähle Anzahl vorhandener Fenster einer Klasse */
/***************************************************************************/
WORD num_windows (WORD class, WORD mode)
{
WORD num;
WINDP window;
num = 0;
for (window=used_list; window!=NULL; window=window->next)
{
if (class==NIL || class==window->class)
if ((mode==SRCH_ANY) ||
(!window->opened && mode==SRCH_CLOSED) ||
( window->opened && mode==SRCH_OPENED))
{
num++;
}
}
return (num);
} /* num_windows */
VOID get_all_windows (WORD class, WORD mode, VOID (*doit)(WINDP window))
{
WINDP window;
for (window=used_list; window!=NULL; window=window->next)
{
if (class==NIL || class==window->class)
if ((mode==SRCH_ANY) ||
(!window->opened && mode==SRCH_CLOSED) ||
( window->opened && mode==SRCH_OPENED))
{
(*doit)(window);
}
}
} /* get_all_windows */
/***************************************************************************/
LOCAL VOID move_to_top (WINDP window)
{
WINDP w;
if (used_list==window) return;
for (w=used_list; w->next!=window; w=w->next) ;
w->next = window->next;
window->next = used_list;
used_list = window;
} /* move_to_top */
/***************************************************************************/
LOCAL VOID move_to_end (WINDP window)
{
WINDP w;
if (used_list==window)
used_list = window->next;
else
{
for (w=used_list; w->next!=window; w=w->next) ;
w->next = window->next;
}
window->next = NULL;
if (used_list==NULL)
used_list = window;
else
{
for (w=used_list; w->next!=NULL; w=w->next) ;
w->next = window;
}
} /* move_to_end */
/***************************************************************************/
/* Einschnappen des Fenster(inneren) auf bestimmte Grenzen */
/* x : auf Bytegrenze (von work) */
/* y : gerade (von work) */
/* w und h : vielfache von xfac und yfac (von scroll) */
/* new ist Innenbereich (work) */
/***************************************************************************/
LOCAL VOID snap_window(WINDP window, RECT *new, WORD mode)
{
new->x = (new->x+4)&(~7); /* Byte Position */
new->y &= (~1); /* gerade Position */
if (mode&WORK_SIZED)
{
new->w = new->w-(new->w%window->xfac);
new->h = new->h-(new->h%window->yfac);
}
if (window->snap != NULL)
(*window->snap) (window, new, mode);
} /* snap_window */
/***************************************************************************/
/* Setze Arbeitsbereich des Fensters */
/* new: Aussenbereich des Fensters */
/***************************************************************************/
LOCAL VOID test_work(RECT *new)
{
/* Liegt und paßt das Fenster auf den Bildschirm */
if (new->y < desk.y)
new->y = desk.y;
else if (new->y > desk.y+desk.h-2*sys_hchar)
new->y = desk.y+desk.h-2*sys_hchar;
if (new->x <= 0)
new->x = -1;
else if (new->x > desk.x+desk.w-3*sys_wchar)
new->x = desk.x+desk.w-3*sys_wchar;
}
LOCAL VOID get_work (WINDP window, RECT *new, WORD mode)
{
if (mode & WORK_SIZED)
{
if (new->w < MIN_WIDTH)
new->w = MIN_WIDTH;
else if (new->w > desk.w)
new->w = desk.w;
if (new->h < MIN_HEIGHT)
new->h = MIN_HEIGHT;
else if (new->h > desk.h)
new->h = desk.h;
}
wind_calc (WC_WORK, window->kind, /* Innenbereich berechnen */
new->x, new->y, new->w, new->h,
&new->x, &new->y, &new->w, &new->h);
snap_window (window, new, mode);
/* work und w_* (und doc) anpassen */
window->work.x = new->x;
window->work.y = new->y;
if (mode & WORK_SIZED)
{
long max_doc;
window->work.w = new->w;
window->w_width = window->work.w / window->xfac;
max_doc = window->doc.w - window->w_width;
if (max_doc < 0)
max_doc = 0;
if (window->doc.x > max_doc) /* Jenseits rechter Bereich */
window->doc.x = max_doc;
window->work.h = new->h;
window->w_hight = window->work.h/window->yfac;
max_doc = window->doc.h - window->w_hight;
if (max_doc < 0)
max_doc = 0;
if (window->doc.y > max_doc) /* Jenseits unterer Bereich */
window->doc.y = max_doc;
}
if (window->opened)
{
wind_calc (WC_BORDER, window->kind, /* Rand berechnen */
new->x, new->y, new->w, new->h,
&new->x, &new->y, &new->w, &new->h);
wind_set (window->handle, WF_CURRXYWH, new->x, new->y, new->w, new->h);
}
if (mode&WORK_SIZED)
set_sliders (window, HORIZONTAL+VERTICAL, SLPOS+SLSIZE);
} /* get_work */
/***************************************************************************/
/* Kreiere Fenster */
/***************************************************************************/
WINDP create_window (WORD kind, WORD class, WORD link, VOID (*crt)(WORD link, WINDP window))
{
WINDP window, w;
WORD i, *ptr, h_age, h_x, h_y;
RECT help;
if (free_list==NULL) /* kein Platz mehr für Fenster */
{
free_list = (WINDP)Malloc(sizeof(WINDOW));
if (free_list==NULL)
{
note(1, NOWINDOW);
return (NULL);
}
else
{
ptr = (WORD*)free_list;
for (i = (short)sizeof(WINDOW) / 2; (--i)>=0; )
*ptr++ = 0;
}
}
/* Unbenutzt und gleiche Klasse und groeszter init */
i = -1;
w = NULL;
for (window=free_list; window!=NULL; window=window->next)
{
if (window->class==class && window->init>i)
{
i = window->init;
w = window;
}
}
window = w;
if (window==NULL)
{
/* Unbenutzt und gleiche Klasse */
for (window=free_list; window!=NULL; window=window->next)
{
if (window->class==class)
break;
}
/* Unbenutzt und nicht gleiche Klasse */
if (window==NULL)
{
for (window=free_list; window!=NULL; window=window->next)
{
if (window->work.w==0)
break;
}
if (window==NULL) /* Nur unbenutzt */
{
window = free_list;
window->work.h = window->work.w = 0;
}
}
}
if (free_list==window) /* Aushängen */
free_list = window->next;
else
{
for (w=free_list; w->next!=window; w=w->next) ;
w->next = window->next;
}
help = window->work; /* Löschen */
h_age = window->age;
h_x = window->icon_x;
h_y = window->icon_y;
#if sizeof(WINDOW)&1
So gehts nicht
#endif
ptr = (WORD*)window;
for (i= (short) sizeof(WINDOW) / 2; (--i)>=0; )
*ptr++ = 0;
if (used_list==NULL) /* Einhängen */
used_list = window;
else
{
for (w=used_list; w->next!=NULL; w=w->next) ;
w->next = window;
}
window->age = h_age;
window->handle = NO_HANDLE;
window->kind = kind;
window->class = class;
window->link = link;
(* crt)(link, window);
if (class != CLASS_ICON)
{
if (help.w == 0 || help.h == 0)
help = window->work;
size_window(window, &help, FALSE);
if (is_icon_on_desk(window->link))
{
if (h_x || h_y)
{
move_icon_to(window->link,h_x,h_y);
show_icon(window->link);
}
else
{
show_icon(window->link);
get_icon_pos(window->link,&window->icon_x,&window->icon_y);
}
}
}
return (window);
} /* create_window */
/***************************************************************************/
/* Öffne Fenster */
/***************************************************************************/
BOOLEAN open_window (WINDP window)
{
WORD wh;
clr_undo();
if (!window->opened) /* Erstes Öffnen */
{
if (window->class == DESK)
wh = DESK;
else
{
wh = wind_create (window->kind, desk.x, desk.y, desk.w, desk.h);
if (wh < 0)
return FALSE; /* Kein Fenster mehr */
}
window->handle = wh;
}
else
wh = window->handle;
unclick_window();
window->opened++; /* Fenster einmal mehr offen */
window->flags &= ~WI_FULLED; /* Fenster hat nicht volle Größe */
if (wh == DESK) /* GEM Desktop */
{
if (!no_desktop)
{
wind_set(DESK, WF_NEWDESK, desktop, 0);
form_dial(FMD_FINISH, 0, 0, 0, 0, desk.x, desk.y, desk.w, desk.h);
}
}
else
{
RECT r;
wind_calc (WC_BORDER, window->kind, /* Rand berechnen */
window->work.x, window->work.y, window->work.w, window->work.h,
&r.x, &r.y, &r.w, &r.h);
if (window->kind&NAME) /* Name setzen */
wind_set (wh, WF_NAME, window->titel);
if (window->kind&INFO) /* Infozeile setzen */
wind_set (wh, WF_INFO, window->info);
window->slider_pos = -1; /* garantiert setzen */
set_sliders (window, HORIZONTAL+VERTICAL, SLPOS+SLSIZE);
if (window->opened==1) /* erstes Öffnen */
{
wind_open (wh, r.x, r.y, r.w, r.h); /* Fenster öffnen */
top_handle = wh;
while (idle())
;
}
}
if (window->opened == 1)
{
move_to_top (window); /* Neu geöffnetes Fenster oben */
if (wh != DESK)
{
redraw_window(window, &window->work);
window->flags |= WI_NOTDRAWED;
}
}
if (wh != DESK)
send_avwinopen(wh);
return TRUE;
} /* open_window */
/***************************************************************************/
/* Schließe Fenster */
/***************************************************************************/
VOID close_window (WINDP window)
{
WORD wh;
wh = window->handle;
unclick_window (); /* Deselektieren */
if (window->opened) /* Fenster offen? */
{
Wake_mouse(); /* Muß an sein */
if (wh==DESK) /* GEM Desktop */
{
if (!no_desktop)
{
wind_set(DESK, WF_NEWDESK, NULL);/* Original Desktop */
form_dial (FMD_FINISH, 0, 0, 0, 0, desk.x, desk.y, desk.w, desk.h);
}
}
else if (window->opened == 1)
{
if (window->close != NULL)
(*window->close) (window);
wind_close (wh); /* Schließe Fenster */
wind_delete (wh); /* Window-Handle freigeben */
if (wh != DESK)
send_avwinclose(wh);
get_realtop();
idle();
}
window->opened--; /* Fenster einmal geschlossen */
if (!window->opened) /* Fenster ganz schließen */
{
window->handle = NO_HANDLE; /* Kein Handle mehr verfügbar */
move_to_end (window);
clr_undo();
}
}
} /* close_window */
/***************************************************************************/
VOID destruct_window(WINDP window)
{
WINDP w;
if (window->flags & WI_ICONIFIED)
window->opened = 1;
while(window->opened)
close_window (window); /* Schließe Fenster */
if (used_list==window) /* Aushängen */
used_list = window->next;
else
{
for (w = used_list; w->next!=window; w=w->next) ;
w->next = window->next;
}
if (window>=windrec && window<&windrec[MAX_WINDOW])
{
if (free_list==NULL || free_list->age>window->age)
{
window->next = free_list;
free_list = window;
}
else
{
for (w=free_list; (w->next!=NULL) && (w->next->age<window->age); w=w->next) ;
window->next = w->next;
w->next = window;
}
}
else
{
Mfree(window);
}
}
/***************************************************************************/
/* Suche und zeichne überlagernde Rechtecke von Fenstern */
/***************************************************************************/
VOID redraw_window (WINDP window, CONST RECT *area)
{
WORD wh;
RECT r1;
if (window==NULL)
return;
if (window->flags & WI_NOTDRAWED)
{
window->flags &= (~WI_NOTDRAWED);
}
else if (window->opened || (window->flags & WI_ICONIFIED) )
{
if (window->flags & WI_ICONIFIED)
{
/* Icon-Position wieder eintragen, da alle Fenster den gleichen
* Objektbaum benutzen!!!
*/
window->icon[0].ob_x = window->ix;
window->icon[0].ob_y = window->iy;
}
wh = window->handle;
if (rc_first (wh, area, &r1))
{
Hide_mouse ();
do
{
if (window->flags & WI_ICONIFIED)
{
if (myrc_intersect (area, &r1))
objc_draw (window->icon, ROOT, MAX_DEPTH, r1.x, r1.y, r1.w, r1.h);
}
else if (window->opened)
{
if (window->draw!=NULL) /* Zeichenroutine ausführen */
(*window->draw) (window, &r1);
}
}
while(rc_next(wh,&r1));
Show_mouse ();
}
}
} /* redraw_window */
/***************************************************************************/
/* Bringt anderes Fenster nach oben */
/***************************************************************************/
VOID cycle_window(VOID)
{
WINDP window, w;
window = NULL;
for (w=used_list; w!=NULL; w=w->next)
{
if (w->opened && w->class != DESK && w->class != CLASS_PROJEKT)
window = w;
}
top_window(window);
}
/***************************************************************************/
/* Räume alle offenen Fenster auf */
/***************************************************************************/
VOID clearup_windows(WORD mode, WORD w, WORD h)
{
WINDP winds[MAX_WINDOW], window;
RECT r1, r2;
WORD i, anz;
for (window=used_list,anz=0; window!=NULL; window=window->next)
{
if (window->opened && window->kind&SIZER && window->flags&WI_TEXT)
winds[anz++] = window;
}
if (anz==0) return;
if (mode==0)
{
r1.x = desk.x+sys_wchar;
r1.y = desk.y+(sys_hchar>>1);
r1.w = desk.w-anz*sys_wchar;
r1.h = desk.h-anz*sys_hchar;
if (w>0 || h>0)
{
wind_calc(WC_WORK, winds[0]->kind, r1.x, r1.y, r1.w, r1.h,
&r1.x, &r1.y, &r1.w, &r1.h);
if (w>0) r1.w = w*gl_wchar;
if (h>0) r1.h = h*gl_hchar;
wind_calc(WC_BORDER, winds[0]->kind, r1.x, r1.y, r1.w, r1.h,
&r1.x, &r1.y, &r1.w, &r1.h);
}
while ((--anz)>=0)
{
size_window(winds[anz], &r1, TRUE);
r1.x += sys_wchar;
r1.y += sys_hchar;
}
return;
}
else if (mode==1) /* nebeneinander */
{
i = (anz+1)>>1;
r1.x = desk.x+sys_wchar;
r1.y = desk.y+(sys_hchar>>1);
r1.w = (desk.w>>1)-i*sys_wchar;
r1.h = desk.h-i*sys_hchar;
r2 = r1;
r2.x += (desk.w>>1);
}
else /* untereinander */
{
i = (anz+1)>>1;
r1.x = desk.x+sys_wchar;
r1.y = desk.y+(sys_hchar>>1);
r1.w = desk.w-i*sys_wchar;
r1.h = (desk.h>>1)-i*sys_hchar;
r2 = r1;
r2.y += (desk.h>>1);
}
while ((--anz)>=0)
{
size_window(winds[anz], (anz&1)?&r2:&r1, TRUE);
if (anz&1)
{
r2.x += sys_wchar;
r2.y += sys_hchar;
}
else
{
r1.x += sys_wchar;
r1.y += sys_hchar;
}
}
}
LOCAL VOID top_qed(VOID)
{
/*
* Unter MagiC kann es passieren, daß oberstes Fenster und Menüzeile
* nicht zur selben APP gehören!
*/
if (magx)
{
WORD id;
/* wind_update(BEG_UPDATE);*/
id = menu_bar(NULL, -1);
/* wind_update(END_UPDATE);*/
if (id != gl_apid)
send_m_special(SMC_SWITCH, gl_apid);
}
}
/***************************************************************************/
/* Fenster wurde durch andere getopped/geuntopped */
/***************************************************************************/
VOID ontop_window(WINDP window)
{
top_qed();
if (window != NULL && window->ontop != NULL)
(*window->ontop)(window);
}
VOID untop_window(WINDP window)
{
if (window != NULL && window->untop != NULL)
(*window->untop)(window);
}
/***************************************************************************/
/* Bringe Fenster nach oben */
/***************************************************************************/
VOID top_window (WINDP window)
{
WORD wh;
top_qed();
if (window == NULL || (!window->opened) && !(window->flags & WI_ICONIFIED))
return;
if (window->class == DESK)
return; /* Desktop im HP */
if (window->top != NULL)
(*window->top)(window);
wh = window->handle;
wind_set (wh, WF_TOP);
top_handle = wh;
if (window != sel_window)
unclick_window();
if (window != used_list) /* War noch nicht top */
{
clr_undo();
move_to_top (window); /* Neues Fenster oben im Keller */
}
} /* top_window */
/************************************************************************/
/* Bringe Fenster nach hinten */
/************************************************************************/
VOID bottom_window (WINDP window, WORD which)
{
WORD wh;
if (window == NULL || (!window->opened) && !(window->flags & WI_ICONIFIED))
return;
if (window->class == DESK)
return;
wh = window->handle;
if (window->bottom != NULL)
(*window->bottom)(window);
if (which == WM_BOTTOMED)
wind_set (wh, WF_BOTTOM); /* MTOS, MagiC >= 3 */
else
wind_set(wh, WF_M_BACKDROP); /* Magic 2 */
if (window != used_list)
{
clr_undo();
move_to_end(window);
}
get_realtop(); /* qed über das neue top-Fenster informieren */
memset(msgbuff, 0, (WORD) sizeof(msgbuff));
msgbuff[0] = WM_TOPPED;
msgbuff[3] = top_handle;
send_msg(gl_apid);
} /* bottom_window */
/***************************************************************************/
/* Scrolle den Fensterinhalt */
/***************************************************************************/
LOCAL VOID scroll_window (WINDP window, WORD dir, long delta)
{
MFDB s, d;
WORD xy[8];
RECT r;
BOOLEAN draw;
draw = FALSE;
wind_get (window->handle, WF_FIRSTXYWH, &r.x, &r.y, &r.w, &r.h);
if (r.w != window->work.w || r.h != window->work.h)
draw = TRUE;
r = window->work; /* Hole workbereich */
if (!myrc_intersect(&desk,&r))
return;
if (dir&HORIZONTAL)
{
delta *= window->xfac;
if (labs(delta) >= r.w)
draw = TRUE;
}
else
{
delta *= window->yfac;
if (labs(delta) >= r.h)
draw = TRUE;
}
if (!draw)
{
rect2array (&r, xy); /* Quelle für vro_cpyfm */
xy[4] = xy[0]; /* Ziel für vro_cpyfm */
xy[5] = xy[1];
xy[6] = xy[2];
xy[7] = xy[3];
if (dir&HORIZONTAL) /* Horizontales Scrolling */
{
if (delta > 0) /* Links Scrolling */
{
xy[0] += (short) delta; /* Werte für vro_cpyfm */
xy[6] -= (short) delta;
r.x += r.w - (short)delta; /* Rechter Bereich nicht gescrollt, */
r.w = (short)delta; /* muß neu gezeichnet werden */
}
else /* Rechts Scrolling */
{
xy[2] += (short)delta; /* Werte für vro_cpyfm */
xy[4] -= (short)delta;
r.w = (short)(-delta); /* Linken Bereich noch neu zeichnen */
}
}
else /* Vertikales Scrolling */
{
if (delta > 0) /* Aufwärts Scrolling */
{
xy[1] += (short)delta; /* Werte für vro_cpyfm */
xy[7] -= (short)delta;
r.y += r.h - (short)delta; /* Unterer Bereich nicht gescrollt, */
r.h = (short) delta; /* muß neu gezeichnet werden */
}
else /* Abwärts Scrolling */
{
xy[3] += (short)delta; /* Werte für vro_cpyfm */
xy[5] -= (short)delta;
r.h = (short)(-delta); /* Oberen Bereich noch neu zeichnen */
}
}
s.fd_addr = d.fd_addr = NULL; /* Erzwinge Bildschirmadresse */
set_clip(FALSE,NULL);
Hide_mouse ();
vro_cpyfm (vdi_handle, S_ONLY, xy, &s, &d);
Show_mouse ();
redraw_window (window, &r);
}
else
redraw_window (window, &r); /* Fenster zeichnen */
} /* scroll_window */
/***************************************************************************/
/* Reagiere auf Anklicken eines Pfeils */
/***************************************************************************/
LOCAL VOID do_arrow(WINDP window, WORD dir, long delta)
{
if (delta)
{
if (dir==HORIZONTAL) /* Horizontale Pfeile und Schieber */
window->doc.x += delta; /* Neue Position */
else /* Vertikale Pfeile und Schieber */
window->doc.y += delta; /* Neue Position */
if (window->opened)
{
set_sliders (window, dir, SLPOS); /* Schieber setzen */
scroll_window (window, dir, delta);
}
}
}
VOID arrow_window (WINDP window, WORD arrow, long amount)
{
WORD w, h, dir;
long oldpos, newpos, max_slide;
if (window!=NULL)
{
w = window->w_width; /* Breite in Zeichen */
h = window->w_hight; /* Höhe in Zeichen */
if (arrow <= WA_DNLINE)
{
oldpos = newpos = window->doc.y;
dir = VERTICAL;
max_slide = window->doc.h - h; /* Maximale Position */
}
else
{
oldpos = newpos = window->doc.x;
dir = HORIZONTAL;
max_slide = window->doc.w - w; /* Maximale Position */
}
switch (arrow)
{
case WA_UPPAGE : newpos -= h * amount; break;
case WA_DNPAGE : newpos += h * amount; break;
case WA_UPLINE : newpos -= amount; break;
case WA_DNLINE : newpos += amount; break;
case WA_LFPAGE : newpos -= w * amount; break;
case WA_RTPAGE : newpos += w * amount; break;
case WA_LFLINE : newpos -= amount; break;
case WA_RTLINE : newpos += amount; break;
}
if (newpos > max_slide) newpos = max_slide; /* Jenseits des Randes */
if (newpos < 0) newpos = 0; /* Jenseits des Randes */
do_arrow(window, dir, newpos-oldpos);
}
} /* arrow_window */
/***************************************************************************/
/* Reagiere auf Bewegen der Schieber */
/***************************************************************************/
VOID h_slider (WINDP window, WORD new_value)
{
WORD w;
long oldpos, newpos, max_slide;
if (window != NULL)
{
w = window->w_width; /* Breite in Zeichen */
max_slide = window->doc.w - w; /* Maximale Position */
oldpos = window->doc.x;
newpos = (long)new_value * max_slide;
newpos = (newpos+500) / 1000; /* Teilen + Runden */
if (newpos > max_slide) newpos = max_slide; /* Jenseits des Randes */
if (newpos < 0) newpos = 0; /* Jenseits des Randes */
do_arrow(window, HORIZONTAL, newpos-oldpos);
}
} /* h_slider */
/*****************************************************************************/
VOID v_slider (WINDP window, WORD new_value)
{
WORD h;
long oldpos, newpos, max_slide;
if (window != NULL)
{
h = window->w_hight; /* Höhe in Zeichen */
max_slide = window->doc.h - h; /* Maximale Position */
oldpos = window->doc.y;
newpos = (long)new_value * max_slide;
newpos = (newpos+500) / 1000; /* Teilen + Runden */
if (newpos > max_slide) newpos = max_slide; /* Jenseits des Randes */
if (newpos < 0) newpos = 0; /* Jenseits des Randes */
do_arrow(window, VERTICAL, newpos-oldpos);
}
} /* v_slider */
/***************************************************************************/
/* Setze Schieberpositionen und Schiebergröße */
/***************************************************************************/
VOID set_sliders (WINDP window, WORD which, WORD mode)
{
WORD wh;
WORD size, newval, oldval;
long max_doc;
if (window->opened)
{
wh = window->handle;
if ((which&HORIZONTAL) && (window->kind&HSLIDE))
{
size = window->w_width;
max_doc = window->doc.w-size;
if (mode&SLPOS)
{
if (max_doc<=0) /* Fenster zu groß oder passend */
newval = 0;
else
newval = (short)((1000L * window->doc.x) / max_doc);
wind_get (wh, WF_HSLIDE, &oldval);
if (newval!=oldval)
wind_set (wh, WF_HSLIDE, newval);
}
if (mode&SLSIZE)
{
if (window->doc.w<=0) /* Fenster zu groß oder passend */
newval = 1000;
else
newval = (short)((1000L * size) / window->doc.w);
wind_get (wh, WF_HSLSIZE, &oldval);
if (newval!=oldval)
wind_set (wh, WF_HSLSIZE, newval);
}
}
if ((which&VERTICAL) && (window->kind&VSLIDE))
{
size = window->w_hight;
max_doc = window->doc.h-size;
if (mode&SLPOS)
{
if (max_doc<=0) /* Fenster zu groß oder passend */
newval = 0;
else
newval = (short)((1000L*window->doc.y) / max_doc);
if (newval!=window->slider_pos)
{
wind_set (wh, WF_VSLIDE, newval);
window->slider_pos = newval;
}
}
if (mode&SLSIZE)
{
if (window->doc.h <= 1) /* Fenster zu groß oder passend */
newval = 1000;
else
newval = (short)((1000L*size) / window->doc.h);
wind_get (wh, WF_VSLSIZE, &oldval);
if (newval!=oldval)
wind_set (wh, WF_VSLSIZE, newval);
}
}
}
} /* set_sliders */
/***************************************************************************/
/* Setze Fenstername */
/***************************************************************************/
VOID set_wname(WINDP window, CONST UBYTE *name)
{
UBYTE str[WINSTRLEN];
strcpy(window->name, name);
strcpy(str, " ");
if (window->changed)
{
strcat(str, "*");
strncat(str, name, WINSTRLEN - 3);
}
else
strncat(str, name, WINSTRLEN - 2);
strcat(str, " ");
strcpy(window->titel, str);
if (window->opened && window->kind & NAME)
wind_set(window->handle, WF_NAME, window->titel);
}
/***************************************************************************/
/* Setze Fensterinfo */
/***************************************************************************/
VOID set_winfo(WINDP window, CONST UBYTE *info)
{
strcpy(window->info, info);
if (window->opened && window->kind & INFO)
wind_set(window->handle, WF_INFO, window->info);
}
/***************************************************************************/
/* '*' vor Fenstertitel */
/***************************************************************************/
VOID change_window (WINDP window, BOOLEAN changed)
{
if (window->changed!=changed)
{
window->changed = changed;
set_wname(window,window->name);
}
}
/***************************************************************************/
/* Vergößere Fenster auf volle Größe bzw. verkleinere Fenster */
/***************************************************************************/
VOID full_window (WINDP window)
{
RECT new;
if (window!=NULL && window->kind&FULLER)
{
if (window->flags&WI_FULLED) /* Mache Fenster klein */
wind_get (window->handle, WF_PREVXYWH, &new.x, &new.y, &new.w, &new.h);
else /* Mache Fenster groß */
wind_get (window->handle, WF_FULLXYWH, &new.x, &new.y, &new.w, &new.h);
test_work (&new);
get_work (window, &new, WORK_MOVED|WORK_SIZED);
window->flags ^= WI_FULLED;
}
} /* full_window */
/***************************************************************************/
/* Ändere Fenstergröße */
/***************************************************************************/
VOID size_window (WINDP window, CONST RECT *new, BOOLEAN border)
{
RECT r;
if (window!=NULL)
{
r = *new;
if (!border)
wind_calc (WC_BORDER, window->kind, /* Rand berechnen */
r.x, r.y, r.w, r.h, &r.x, &r.y, &r.w, &r.h);
if (window->kind&SIZER)
{
test_work (&r);
get_work (window, &r, WORK_SIZED);
window->flags &= ~WI_FULLED;
if (window->flags&WI_REDRAW)
redraw_window(window,&window->work);
}
else
move_window(window,&r);
}
} /* size_window */
/***************************************************************************/
/* Bewege Fenster */
/***************************************************************************/
VOID move_window (WINDP window, CONST RECT *new)
{
if (window != NULL)
{
if (window->flags & WI_ICONIFIED)
{
WORD x, y, d;
wind_set(window->handle, WF_CURRXYWH, new->x, new->y, new->w, new->h);
wind_get(window->handle, WF_WORKXYWH, &x, &y, &d, &d);
window->icon[0].ob_x = x;
window->icon[0].ob_y = y;
window->ix = window->icon[0].ob_x;
window->iy = window->icon[0].ob_y;
}
else if (window->kind & MOVER)
{
RECT r;
r = *new;
/* test_work (&r); hier nicht wg. MagiX */
get_work (window, &r, WORK_MOVED);
window->flags &= ~WI_FULLED;
}
}
} /* move_window */
/***************************************************************************/
/* Iconify */
/***************************************************************************/
VOID iconify_window(WINDP window, CONST RECT *new, BOOLEAN flag)
{
unclick_window (); /* Deselektieren */
if (window->opened && !(window->flags & WI_ICONIFIED))
{
WORD x, y, w, h;
if (window->iconify != NULL)
(*window->iconify) (window);
/* alte Größe merken */
wind_get(window->handle, WF_CURRXYWH, &window->old_size.x, &window->old_size.y,
&window->old_size.w, &window->old_size.h);
wind_set(window->handle, WF_ICONIFY, new->x, new->y, new->w, new->h);
if (flag) /* alliconify: Fenster erst noch öffnen! */
wind_open(window->handle, new->x, new->y, new->w, new->h);
wind_get(window->handle, WF_WORKXYWH, &x, &y, &w, &h);
window->icon[0].ob_x = x;
window->icon[0].ob_y = y;
window->icon[0].ob_width = w;
window->icon[0].ob_height = h;
window->icon[1].ob_x = (w - window->icon[1].ob_width) / 2;
window->icon[1].ob_y = (h - window->icon[1].ob_height) / 2;
window->ix = window->icon[0].ob_x;
window->iy = window->icon[0].ob_y;
window->flags |= WI_ICONIFIED;
if (window->class == CLASS_EDIT)
window->flags &= ~WI_MOUSE;
window->opened = 0;
bottom_window(window, WM_BOTTOMED);
}
}
LOCAL VOID crt_wicon(WORD icon, WINDP window)
{
window->opened = 1; /* wir gaukeln iconify_window ein geöffnetes Fenster
* vor, damit der Iconify klappt.
*/
window->icon = winicon;
}
VOID alliconify(CONST RECT *new)
{
WORD i, anz;
WORD ic, icp[MAX_ICON_ANZ];
WINDP window;
if (makro_rec)
{
mybeep();
return;
}
/* Zunächst alle Fenster schließen und in Liste merken */
i = all_icons(icp);
anz = 0;
while ((--i) >= 0)
{
ic = icp[i];
if (ic != 0)
{
window = get_window(ic);
if (window != NULL)
if (window->handle != NO_HANDLE && ((window->opened) || (window->flags & WI_ICONIFIED)))
{
anz++;
opened_win[anz] = ic;
wind_close(window->handle);
if (window->flags & WI_ICONIFIED)
{
/*
* Iconify noch schnell aufheben. Schwachsinnige Größe macht nix,
* Fenster wird eh schon zu.
*/
if (window->uniconify != NULL)
(*window->uniconify) (window);
wind_set(window->handle, WF_UNICONIFY, -1, -1, -1, -1);
window->flags &= ~WI_ICONIFIED;
if (window->class == CLASS_EDIT)
window->flags |= WI_MOUSE;
}
wind_delete(window->handle); /* Fenster entgültig löschen */
window->handle = NO_HANDLE;
window->opened = 0;
}
}
}
opened_win[0] = anz;
/*
* Nachdem nun alle anderen Fenster geschlossen wurden, wird ein
* neues Fenster geöffnet. Etwas umständlich, aber 'open_window' macht
* viel zuviele Dinge mit dem Fenster, die ggf. gar nicht funken.
*/
icon_win = create_window((NAME|MOVER), CLASS_ICON, 0, crt_wicon);
icon_win->handle = wind_create((NAME|MOVER), desk.x, desk.y, desk.w, desk.h);
set_wname(icon_win, " qed ");
iconify_window(icon_win, new, TRUE); /* Als Icon anmelden und öffnen! */
bottom_window(icon_win, WM_BOTTOMED); /* Icon nach hinten! */
enable_menu(FALSE); /* Menu abschalten */
all_iconified = TRUE;
}
VOID uniconify_window(WINDP window, CONST RECT *new)
{
WORD i;
RECT r;
if (all_iconified)
{
wind_close(icon_win->handle); /* Icon schließen */
wind_set(icon_win->handle, WF_UNICONIFY, -1, -1, -1, -1);
destruct_window(icon_win); /* und entgültig löschen */
enable_menu(TRUE); /* Menu wieder an */
all_iconified = FALSE;
i = 1; /* und alle Fenster wieder öffnen */
while (i <= opened_win[0])
{
window = get_window(opened_win[i]);
open_window(window);
i++;
}
}
else if (window != NULL && (window->flags & WI_ICONIFIED))
{
if (window->uniconify != NULL)
(*window->uniconify) (window);
wind_calc(WC_BORDER, window->kind,
window->work.x, window->work.y, window->work.w, window->work.h,
&r.x, &r.y, &r.w, &r.h);
/* Wurde Font gewechselt während Fenster iconifiziert? */
if (window->old_size.w != r.w)
new = &r;
if (new == NULL)
wind_set(window->handle, WF_UNICONIFY, window->old_size.x, window->old_size.y,
window->old_size.w, window->old_size.h);
else
wind_set(window->handle, WF_UNICONIFY, new->x, new->y, new->w, new->h);
window->flags &= ~WI_ICONIFIED;
if (window->class == CLASS_EDIT)
window->flags |= WI_MOUSE;
window->opened = 1;
top_window(window);
}
}
/***************************************************************************/
/* Zeichensatz wurde geändert */
/***************************************************************************/
GLOBAL VOID do_font_change(WINDP window)
{
RECT r;
if (window->flags & WI_FONTSIZE)
{
window->xfac = gl_wchar;
window->yfac = gl_hchar;
r.x = window->work.x;
r.y = window->work.y;
r.w = window->work.w;
r.h = gl_hchar * window->w_hight;
if ((r.h + r.y) > desk.h)
r.h = desk.h - r.y;
size_window(window, &r, FALSE);
redraw_window(window, &window->work);
}
}
/***************************************************************************/
/* Klicken in das Fensterinnere */
/***************************************************************************/
VOID click_window (WINDP window, MKINFO *mk)
{
if (window!=NULL)
{
if (window->click!=NULL)
(*window->click) (window, mk);
else
unclick_window (); /* Deselektieren */
}
} /* click_window */
/***************************************************************************/
VOID unclick_window (VOID)
{
if (sel_window!=NULL && sel_window->unclick!=NULL)
(*sel_window->unclick) (sel_window);
sel_window = NULL;
setclr (sel_objs);
} /* unclick_window */
/***************************************************************************/
/* Taste für ein Fenster */
/***************************************************************************/
BOOLEAN key_window (WINDP window, MKINFO *mk)
{
if (window->key!=NULL)
return ((*window->key) (window, mk));
return (FALSE);
} /* key_window */
/***************************************************************************/
/* Scroll- und Löschroutinen */
/***************************************************************************/
VOID scroll_vertical (CONST RECT *area, WORD delta)
/* Die Maus ist schon aus, keine Überprüfung auf Bildschirmgrenzen */
{
MFDB s, d;
WORD xy[8];
rect2array (area, xy);
xy[4] = xy[0];
xy[5] = xy[1]-delta;
xy[6] = xy[2];
xy[7] = xy[3]-delta;
s.fd_addr = d.fd_addr = NULL; /* Erzwinge Bildschirmadresse */
vro_cpyfm (vdi_handle, S_ONLY, xy, &s, &d); /* Eigentliches Scrolling */
} /* scroll_vertical */
/***************************************************************************/
VOID clr_area (CONST RECT *area)
{
WORD xy[4];
rect2array (area, xy); /* Bereich setzen */
if (fill_color!=WHITE)
{
vsf_color(vdi_handle,WHITE);
fill_color = WHITE;
}
vr_recfl (vdi_handle, xy); /* Bereich löschen */
} /* clr_area */
/***************************************************************************/
/* Initialisieren des Moduls */
/***************************************************************************/
VOID init_windows (VOID)
{
WINDP window;
WORD i, *ptr;
sel_window = NULL; /* Kein Fenster angewählt */
setclr (sel_objs); /* Keine Objekte selektiert */
used_list = NULL;
age = 0;
ptr = (WORD*)&windrec[MAX_WINDOW]; /* letzen (von hinten) löschen */
for (i= (short) sizeof(WINDOW)/2; (--i)>=0; )
*(--ptr) = 0;
free_list = window = &windrec[0];
for (i=MAX_WINDOW-1; (--i)>=0; window++)
{
COPYW(window,ptr, (short)sizeof(WINDOW));
window->age = age++;
window->next = &window[1];
}
window->age = age++;
window->next = NULL;
} /* init_windows */